Анализ и визуализация данных
Визуализация данных с помощью библиотеки Makie
Makie — это экосистема визуализации данных для языка программирования Julia, отличающаяся высокой производительностью и расширяемостью. Makie превращает ваши данные в красивые изображения или анимации.
В этом разделе рассмотрим базовые приемы работы с Makie.
Установка
Makie предлагает четыре различных бэкенда:
GLMakie(на основе OpenGL, интерактивный);CairoMakie(на основе Cairo, статическая векторная графика);WGLMakie(на основе WebGL, с отображением графиков в браузере);RPRMakie(экспериментальная трассировка лучей с использованием RadeonProRender).
Для интерактивных графиков с ускорением на GPU рекомендуется использовать GLMakie, а для статической векторной графики — CairoMakie.
Нужный бэкенд устанавливается с помощью диспетчера пакетов Julia Pkg. Например:
Pkg.add("CairoMakie")
Устанавливать библиотеку Makie.jl отдельно не требуется, так как она экспортируется каждым пакетом бэкенда.
Построение двумерных графиков
Линейные и точечные графики
Будем пользоваться библиотекой CairoMakie. Сначала загрузим ее:
using CairoMakie
Зададим данные для построения графика. Они представляют собой несколько воображаемых измерений, выполненных в течение двух секунд. Здесь x — отсчеты времени, а y — значения измеряемой величины:
x = 0:0.1:2
y = [8.2, 8.4, 6.3, 9.5, 9.1, 10.5, 8.6, 8.2, 10.5, 8.5, 7.2, 8.8, 9.7, 10.8, 12.5, 11.6, 12.1, 12.1, 15.1, 14.7, 13.1];
Сначала построим линейный график. В Makie линейные графики строятся с помощью функции lines.
lines(x, y)
Чтобы построить точечный график (т.е. отобразить каждую точку данных как отдельный маркер), воспользуемся функцией scatter. Функции с таким именем существуют и в других библиотеках Julia, поэтому, чтобы выбрать нужную функцию, мы перед ее именем должны написать через точку имя библиотеки, которой она принадлежит: CairoMakie.scatter.
CairoMakie.scatter(x, y)
Наша цель — показать данные измерений вместе с линией, представляющей приближение экспериментальных данных показательной функцией . Ее можно построить в виде линии:
lines(x, exp.(x) .+ 7)
Теперь мы хотим, чтобы график рассеяния и линейный график были наложены друг на друга.
Можно построить два графика на одном полотне с помощью функций построения графиков, которые оканчиваются на !. Для вывода графика на экран используется функция current_figure().
CairoMakie.scatter(x, y)
lines!(x, exp.(x) .+ 7)
current_figure()
✏️Задание 1
Задайте два массива экспериментальных данных:
t = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
u = [2.1, 3.8, 6.1, 7.7, 10.2, 12.3, 13.9, 16.1, 17.8, 20.3]
С помощью функций библиотеки CairoMakie постройте на одном полотне два графика:
- точечный график экспериментальных данных ;
- линейный график аппроксимирующей функции .
Решение
t = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
u = [2.4, 3.8, 6.3, 7.6, 10.3, 12.3, 13.7, 16.2, 17.7, 20.4]
CairoMakie.scatter(t, u)
lines!(t, 2 .* t)
current_figure()
Объекты Figure и Axis
Figure — это самый внешний объект-контейнер. Axis представляет собой один из типов объектов оси. Объект Axis можно поместить в объект Figure, а затем выполнить построение.
Построим график из предыдущего примера с использованием этих объектов:
f = Figure()
ax = Axis(f[1, 1])
CairoMakie.scatter!(ax, x, y)
lines!(ax, x, exp.(x) .+ 7)
f
Здесь обе функции, CairoMakie.scatter! и lines!, явно построены в блоке Axis, который мы помещаем в блок Figure. Axis(f[1, 1]) означает, что мы помещаем Axis в макет Figure в позицию строки 1 столбца 1.
Теперь зададим в блоке Axis заголовок, а также метки осей x и y:
f = Figure()
ax = Axis(f[1, 1],
title = "Experimental data and exponential fit",
xlabel = "Time (seconds)",
ylabel = "Value"
)
CairoMakie.scatter!(ax, x, y)
lines!(ax, x, exp.(x) .+ 7)
f
✏️Задание 2
По экспериментальным данным из Задания 1 с помощью объектов Figure и Axis постройте на одном полотне два графика:
- точечный график экспериментальных данных ;
- линейный график аппроксимирующей функции .
Задайте заголовок графика "Экспериментальные данные и линейная аппроксимация" и подписи по осям "Время, с" и "Значение".
Решение
f = Figure()
ax = Axis(f[1, 1],
title = "Экспериментальные данные и линейная аппроксимация",
xlabel = "Время, с",
ylabel = "Значение"
)
CairoMakie.scatter!(ax, t, u)
lines!(ax, t, 2 .* t)
f
Применение стиля к графикам
Функции построения графиков принимают множество различных атрибутов стиля в качестве именованных аргументов.
Изменим в нашем примере цвет символов первого графика на красный (color=:red), цвет линии второго графика — на зеленый (color=:green), стиль линий второго графика — на linestyle=:dash, а толщину линии второго графика зададим равной 3 (linewidth=:3).
f = Figure()
ax = Axis(f[1, 1],
title = "Experimental data and exponential fit",
xlabel = "Time (seconds)",
ylabel = "Value"
)
CairoMakie.scatter!(ax, x, y, color = :red)
lines!(ax, x, exp.(x) .+ 7, color = :green, linestyle = :dash, linewidth = :3)
f
Условные обозначения
Еще один элемент графика, которого нам не хватает, — условные обозначения. Одним из способов создания условных обозначений является пометка графиков с помощью ключевого слова label и использование функции axislegend.
f = Figure()
ax = Axis(f[1, 1],
title = "Experimental data and exponential fit",
xlabel = "Time (seconds)",
ylabel = "Value",
)
CairoMakie.scatter!(
ax,
x,
y,
color = :red,
label = "Measurements"
)
lines!(
ax,
x,
exp.(x) .+ 7,
color = :green,
linestyle = :dash,
linewidth = :3,
label = "f(x) = exp(x) + 7",
)
axislegend(position = :rb)
f
✏️Задание 3
Модифицируйте график, построенный в Задании 2:
- Задайте цвет символов первого графика синим (
:blue). - Задайте обозначение первого графика
label = "Измерения". - Задайте цвет линии второго графика красным.
- Задайте стиль линии второго графика
:dash. - Задайте толщину линии второго графика равной 2.
- Задайте обозначение второго графика
label = "u(t)=2t".
Решение
f = Figure()
ax = Axis(f[1, 1],
title = "Экспериментальные данные и линейная аппроксимация",
xlabel = "Время, с",
ylabel = "Значение"
)
CairoMakie.scatter!(ax, t, u, color = :blue, label = "Измерения")
lines!(ax, t, 2 .* t, color = :red, linestyle = :dash, linewidth = :2, label = "u(t) = 2x")
axislegend(position = :rb)
f
Построение трехмерных графиков
Makie предоставляет широкие возможности для построения трехмерных графиков.
В качестве примера рассмотрим построение спиральной линии в пространстве:
a, m, z₀ = 1, 2.1, 0
φ = range(0, 20π, length=500)
r = a*φ
x, y, z = r .* cos.(φ), r .* sin.(φ), m .* r .+ z₀;
with_theme(theme_black()) do
fig = Figure(size = (1200, 800))
ax = LScene(fig[1,1])
line3d = lines!(x, y, z, color = z, colormap = :viridis)
lines!(x, y, 0*z, color = z, colormap = (:viridis, 0.65))
axis = ax.scene[OldAxis]
axis[:names, :axisnames] = ("x", "y", "z")
axis[:names, :fontsize] = 10
axis[:names, :textcolor] = (:red, :green, :white)
axis[:names, :font] = "helvetica"
axis[:names, :gap] = 5
axis[:ticks, :textcolor] = :white
axis[:ticks, :fontsize] = 5
Colorbar(fig[1,2], line3d, label = "z",ticklabelsize = 14,
width = 12, height = Relative(2/4), tickalign=0)
fig
end
Еще один пример — построение графика поверхности и тепловой карты для функции :
x = y = -5:0.5:5
z = x .^ 2 .+ y' .^ 2
cmap = :plasma
with_theme(colormap = cmap) do
fig = Figure(fontsize = 22)
ax3d = Axis3(fig[1, 1]; aspect = (1, 1, 1),
perspectiveness = 0.5, azimuth = 2.19, elevation = 0.57)
ax2d = Axis(fig[1, 2]; aspect = 1, xlabel = "x", ylabel="y")
pltobj = CairoMakie.surface!(ax3d, x, y, z; transparency = true)
CairoMakie.heatmap!(ax2d, x, y, z; colormap = (cmap, 0.65))
CairoMakie.contour!(ax2d, x, y, z; linewidth = 2, levels = 12, color = :black)
CairoMakie.contour3d!(ax3d, x, y, z; linewidth = 4, levels = 12,
transparency = true)
Colorbar(fig[1, 3], pltobj; label="z", labelrotation=pi)
colsize!(fig.layout, 1, Aspect(1, 1.0))
colsize!(fig.layout, 2, Aspect(1, 1.0))
resize_to_layout!(fig)
fig
end
✏️Задание 4
Пользуясь предыдущим примером, постройте график поверхности и тепловую карту для функции в диапазоне изменения аргументов x и y от -10 до 10 с шагом 0.1.
Решение
x = y = -10:0.1:10
z = x .^ 4 .+ y' .^ 4
cmap = :plasma
with_theme(colormap = cmap) do
fig = Figure(fontsize = 22)
ax3d = Axis3(fig[1, 1]; aspect = (1, 1, 1),
perspectiveness = 0.5, azimuth = 2.19, elevation = 0.57)
ax2d = Axis(fig[1, 2]; aspect = 1, xlabel = "x", ylabel="y")
pltobj = CairoMakie.surface!(ax3d, x, y, z; transparency = true)
CairoMakie.heatmap!(ax2d, x, y, z; colormap = (cmap, 0.65))
CairoMakie.contour!(ax2d, x, y, z; linewidth = 2, levels = 12, color = :black)
CairoMakie.contour3d!(ax3d, x, y, z; linewidth = 4, levels = 12,
transparency = true)
Colorbar(fig[1, 3], pltobj; label="z", labelrotation=pi)
colsize!(fig.layout, 1, Aspect(1, 1.0))
colsize!(fig.layout, 2, Aspect(1, 1.0))
resize_to_layout!(fig)
fig
end
Сохранение графика
График можно сохранить в файл с помощью функции save. Наиболее распространенными форматами являются png для изображений, а также svg или pdf для векторной графики.
Сохраним последний построенный график в трех форматах:
save("figure.png", fig)
save("figure.svg", fig)
save("figure.pdf", fig)
Теперь в папке данного курса должны находиться три файла figure.png, figure.svg и figure.pdf.
Больше о работе с Makie вы можете узнать на странице документации, а также на сайте Beautiful Makie.